import { AxiosResponse } from "axios"

interface RequestQueueItem {
  key: string
  lastReqTime: number
  instance: Promise<AxiosResponse<any, any>>
}
export default {
  records: new Map<string, RequestQueueItem>(),
  recordRequest: function (item: RequestQueueItem) {
    const { key } = item
    return this.records.set(key, item)
  },
  removeRecordRequest (key: string) {
    this.records.delete(key)
    this.onResponseEvents.delete(key)
    this.cacheLastResult.delete(key)
  },
  isRepeatRequest: function (key: string) {
    const record = this.records.get(key)
    if (record) {
      if (Date.now() - record.lastReqTime < 300) {
        return true
      }
    }
    return false
  },
  cacheLastResult: new Map<string, any>(),
  repeatRequestEnd: function (key: string) {
    return new Promise<any>((resolve, reject) => {

      const result = this.cacheLastResult.get(key)

      if (result && result.error) {
        reject(result.error)
        return
      }

      if (result && result.response) {
        resolve(result.response)
        return
      }

      this.subscribe(key, (response: any) => {
        this.cacheLastResult.set(key, {response})
        resolve(response)
      }, (error: any) => {
        this.cacheLastResult.set(key, {error})
        reject(error)
      })
    })
  },
  onResponseEvents: new Map<string, any[]>(),
  boradcastResolve (key: string, response: any) {
    const events = this.onResponseEvents.get(key)
    if (events && events.length > 0) {
      events.forEach((event) => {
        event.resolve && event.resolve(response)
      })
    }
  },
  boradcastReject (key: string, err: any) {
    const events = this.onResponseEvents.get(key)
    if (events && events.length > 0) {
      events.forEach((event) => {
        event.reject && event.reject(err)
      })
    }
  },
  subscribe (key: string, resolve: any, reject: any) {
    const events = this.onResponseEvents.get(key)
    if (events) {
      events.push({ resolve, reject })
    } else {
      this.onResponseEvents.set(key, [{ resolve, reject }])
    }
  }
}
